#include <iostream>
#include <cstring>

#define NAMESIZE 256

using namespace std;

class Person {
	protected:
		char *m_name;
		int m_age;
	public:
		Person(const char *name, int age);
		~Person();
		void setName(const char *name);
		void setAge(int age);
		void AAA(int a)
		{
			cout << "Base " << a << endl;
		}
};

class Student : public Person {
	private:
		int m_score;
		static int totalCount;
		static int totalScore;
	public:
		Student(const char *name, int age, int score);
		Student(const Student &s);
		~Student();
		void setScore(int score);
		static int getTotalCount();
		static double getAvgScore();
		friend void showStudent(const Student &s);
		void AAA(int a, int b) // Shadow AAA(int a) in base class, with different parameter list. AAA(int a) will not be available for Student objects.
		{
			cout << "Child " << a << endl;
		}
};

int Student::totalCount = 0;
int Student::totalScore = 0;

Person::Person(const char *name, int age) : m_age(age)
{
	m_name = new char[NAMESIZE];
	strncpy(m_name, name, NAMESIZE);
}

Person::~Person()
{
	cout << "Person '" << m_name << "' destructed" << endl;
	delete m_name;
	m_name = nullptr;
}

Student::Student(const char *name, int age, int score) : Person(name, age), m_score(score)
{
	totalCount += 1;
	totalScore += m_score;
}

Student::Student(const Student &s) : Person(s.m_name, s.m_age), m_score(s.m_score)
{
	totalCount += 1;
	totalScore += m_score;
}

Student::~Student()
{
	cout << "Student destructed" << endl;
	totalCount -= 1;
	totalScore -= m_score;
}

void showStudent(const Student &s)
{
	cout << "Name: " << s.m_name << ", Age: " << s.m_age << ", Score: " << s.m_score << endl;
}

void Person::setName(const char *newName)
{
	memset(m_name, '\0', NAMESIZE);
	strncpy(m_name, newName, NAMESIZE);
}

void Person::setAge(int newAge)
{
	m_age = newAge;
}

void Student::setScore(int newScore)
{
	totalScore -= m_score;

	m_score = newScore;

	totalScore += m_score;
}

int Student::getTotalCount()
{
	return totalCount;
}

double Student::getAvgScore()
{
	return (double) totalScore / totalCount;
}

int main(void)
{
	Student s1("Alice", 20, 98);
	Student s2(s1);

	s2.setName("Bob");
	s2.setAge(22);
	s2.setScore(86);

	showStudent(s1);
	showStudent(s2);

	// Cast to Person object to access AAA(int a) method.
	reinterpret_cast<Person *>(&s2)->AAA(42);

	cout << "Current count: " << Student::getTotalCount() << ", Avg score: " << Student::getAvgScore() << endl;

	return 0;
}

